/**
 * @brief 共享内存模块，用来和其他进程通讯提供系统的基础信息
 * @version 1.0
 * @author 宋炜
 */

#pragma once

#include <semaphore.h>
#include <sys/mman.h>

#include <string>
#include <mutex>

/// 信号量模块
class semaphore
{
private:
	std::string    m_name__;
	// 避免本地线程竞争
	std::mutex     m_mutex__;
	sem_t        * p_sem__;
public:
	/**
	 * @brief 构造信号量
	 * @param name[ I ], 信号量的名字
	 * @param svr[ I ], 是否是生产者端，true则会创建信号量，否则打开信号量
	 */
	semaphore( const std::string& name , bool svr = true );
	~semaphore();
	/**
	 * @brief 锁定或者解锁操作
	 */
	bool lock( bool sw = true);
	bool unlock(){ return lock( false ); }
	/**
	 * @brief 尝试锁定或者解锁
	 */
	bool tryLock( bool sw );
	bool tryUnlock(){ return tryLock( false ); }
};

/// 信号量守护模块，利用C++闭包方便的进行加锁和解锁
class smfLockGuard
{
private:
	semaphore& m_sem__;
public:
	explicit smfLockGuard( semaphore& sm );
	~smfLockGuard();
};

/// 共享内存	
class sharedMem
{
private:
	std::string   m_name__;             // 
	uint8_t     * p_shared_mem__;       // 共享内存在当前进程中的映射
	uint64_t      m_size__;             // 共享内存的大小
	uint64_t      m_data_len__;         // 实际的数据长度

	semaphore     m_smf__;              // 信号量

	int           m_fd__;
public:
	/**
	 * @brief
	 * @param name[ I ], 共享内存名称。信号量名称则是在内存名称加上后缀 "_smf"
	 * @param size[ I ], 共享内存大小
	 * @exception 创建失败抛出std::runtime_error
	 */
	sharedMem( const std::string& name , uint64_t size , bool svr = true );
	~sharedMem();

	size_t send( const uint8_t * data ,size_t len );
	/**
	 */
	size_t recv( uint8_t * data , size_t len );
};

